package com.rabbitmq.spring.config;

import com.rabbitmq.client.BuiltinExchangeType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import static com.rabbitmq.common.constants.CommonConstants.SPRING_EXCHANGE_NAME_PREFIX;


/**
 * @author
 * @Describe 功能描述
 * @date
 */
@Configuration
@Slf4j(topic = "RabbitMqConfig")
public class RabbitMqConfig {

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate();

        rabbitTemplate.setConnectionFactory(connectionFactory);
        // 设置Mandatory为开启,这样才能触发回调函数。无论消息推送结果怎么样都会强制调用回调函数
        rabbitTemplate.setMandatory(true);

        // 生产者推送消息的消息确认调用回调函数(是否推送到交换机)
        // 1.生产者将消息发送到不存在的交换机上
        // 2.生产者发送消息到了存在的交换机上，但该交换机并没有绑定队列
        // 3.生产者将消息发送到交换机上并并绑定的队列接收
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            log.info("ConfirmCallback关联数据：{}", correlationData);
            log.info("ConfirmCallback确认情况：{}", ack);
            log.info("ConfirmCallback原因：{}", cause);
        });

        // 生产者推送消息的消息回退调用回调函数(是否推送到队列)
        // 1.生产者发送消息到了存在的交换机上，但该交换机并没有绑定队列
        rabbitTemplate.setReturnsCallback(returnedMessage -> {
            log.info("ReturnCallback消息：{}", returnedMessage.getMessage());
            log.info("ReturnCallback回应码：{}", returnedMessage.getReplyText());
            log.info("ReturnCallback交换机：{}", returnedMessage.getExchange());
            log.info("ReturnCallback路由键：{}", returnedMessage.getRoutingKey());
        });

        return rabbitTemplate;
    }

    /**
     * 没有绑定个队列的交换机，用来测试发送到该交换的消息是否会进行确认回调
     *
     * @return
     */
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(SPRING_EXCHANGE_NAME_PREFIX + BuiltinExchangeType.DIRECT.getType() + "_publishExchangeWithoutQueueBind");
    }
}
